﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Eflong.DTO.Wcf;
using Eflong.MonitoringLib.MonitoringUnit;
using Eflong.Utility;

using Modalities = Eflong.MonitoringLib.MonitoringUnit.MonitoringUnitModality.Modalities;

namespace Eflong.Monitor
{
    public enum AlertAndFault { None = 0 , Alert = 1 , Fault = 2 , AlertFault = 3 };

    public class MonitorInfo
    {
        # region Singleton 模式  MonitorInfo

        private static MonitorInfo _Instance;

        private MonitorInfo( )
        {
            list_ExcessRecord = new List<ExcessRecord>( );
            List_SensorAlertInfo = new List<SensorAlertInfo>( );
            List_SensorFaultInfo = new List<SensorFaultInfo>( );
            List_SensorInfo = new List<SensorInfo>( );

            // logger = EflogMonitorServer.GetInstance().logger;
        }

        public static MonitorInfo Instance( )
        {
            if ( _Instance == null )
            {
                _Instance = new MonitorInfo( );
            }
            return _Instance;
        }

        #endregion

        // private object syncObject = new object();

        /// <summary>
        /// 当前最新报警的集合
        /// </summary>

        #region 异常记录处理

        /// <summary>
        /// 需要处理的异常记录的集合
        /// </summary>
        ///
        private List<ExcessRecord> list_ExcessRecord;

        /// <summary>
        /// 加入一批需要处理的实时数据记录,作为异常处理的原始数据
        /// </summary>
        /// <param name="records"></param>
        public void AddExcessRecords( List<ExcessRecord> records )
        {
            lock ( syncObject )
            {
                list_ExcessRecord.AddRange( records.ToArray( ) );

                records.Clear( );
            }
        }

        private Dictionary<int , List<string>> dic_DeletedIds = new Dictionary<int , List<string>>( );

        /// <summary>
        /// 加入一批需要删除的测点
        /// </summary>
        /// <param name="nId"></param>
        /// <param name="Ids"></param>
        public void AddDeletedSensord( int nId , string[ ] Ids )
        {
            lock ( syncObject )
            {
                if ( dic_DeletedIds.ContainsKey( nId ) )
                {
                    dic_DeletedIds[ nId ].AddRange( Ids );
                }
                else
                {
                    dic_DeletedIds.Add( nId , new List<string>( Ids ) );
                }
            }
        }

        public Dictionary<int , List<string>> TakeDeletedSensors( )
        {
            Dictionary<int , List<string>> dic = new Dictionary<int , List<string>>( );
            lock ( syncObject )
            {
                foreach ( var id in dic_DeletedIds.Keys )
                {
                    if ( dic_DeletedIds[ id ].Count > 0 )
                    {
                        string symbol;
                        foreach ( string s in dic_DeletedIds[ id ] )
                        {
                            symbol = id.ToString( ) + "-" + s;
                            if ( dic_SensorInfos.ContainsKey( symbol ) )
                            {
                                dic_SensorInfos.Remove( symbol );
                            }
                        }
                        dic.Add( id , dic_DeletedIds[ id ] );
                        dic_DeletedIds[ id ].Clear( );
                    }
                }
            }
            return dic;
        }

        public List<SensorInfo> TakeAnalogSensors( DateTime time )
        {
            List<SensorInfo> infos = null;
            lock ( syncObject )
            {
                infos = dic_SensorInfos.Values.ToList( ).FindAll( sensor => sensor.Modality == Modalities.Analog && sensor.tmUpdate >= time ).ToList( );
            }
            return infos;
        }

        public List<SensorInfo> TakeDigitalSensors( DateTime time )
        {
            List<SensorInfo> infos = null;
            lock ( syncObject )
            {
                infos = dic_SensorInfos.Values.ToList( ).FindAll( sensor => sensor.Modality == Modalities.Digital && sensor.tmUpdate >= time ).ToList( );
            }
            return infos;
        }

        /// <summary>
        /// 取出一批实时数据记录，进行报警及故障的相关处理
        /// </summary>
        /// <returns></returns>
        public List<ExcessRecord> TakeExcessRecords( )
        {
            List<ExcessRecord> list = new List<ExcessRecord>( );
            lock ( syncObject )
            {
                list = list_ExcessRecord.ToList( );
                list_ExcessRecord.Clear( );
            }
            return list;
        }

        #endregion

        #region 传感器报警记录处理

        /// <summary>
        /// 当前的传感器报警记录表
        /// </summary>
        private List<ExcessRecord> list_AlertRecord = new List<ExcessRecord>( );

        /// <summary>
        ///
        /// </summary>
        private List<Int32> list_AlertRecord_AutoId = new List<Int32>( );

        //public ExcessRecord TakeAlertRecord()
        //{
        //    ExcessRecord ar = new ExcessRecord();
        //    lock (list_AlertRecord)
        //    {
        //        if (list_AlertRecord.Count > 0)
        //        {
        //            ar = list_AlertRecord[0];
        //            list_AlertRecord.RemoveAt(0);
        //        }
        //    }
        //    return ar;
        //}

        #endregion

        /// <summary>
        /// 最新 24小时的传感器报警信息明细表,有重复的记录
        /// </summary>
        private List<SensorAlertInfo> list_AlertInfoHistory = new List<SensorAlertInfo>( );

        private List<SensorAlertInfo> list_CurrentAnalogAlertInfo = new List<SensorAlertInfo>( );

        private List<SensorAlertInfo> list_CurrentDigitalAlertInfo = new List<SensorAlertInfo>( );

        private List<SensorFaultInfo> list_CurrentFaultInfo = new List<SensorFaultInfo>( );

        /// <summary>
        /// 已解除当前模拟量报警表的记录信息
        /// </summary>
        private List<SensorAlertInfo> list_AnalogAlertRecordNowForDelete = new List<SensorAlertInfo>( );

        /// <summary>
        /// 已解除的当前开关量报警表的信息
        /// </summary>
        private List<SensorAlertInfo> list_digitalAlertRecordNowForDelete = new List<SensorAlertInfo>( );

        /// <summary>
        /// 已解除的当前故障表的信息
        /// </summary>
        private List<SensorFaultInfo> list_FaultRecordNowForDelete = new List<SensorFaultInfo>( );

        //private List<SensorAlertInfo> list_AlertInfoNow = new List<SensorAlertInfo>();

        /// <summary>
        /// 当前传感器报警的字典
        /// </summary>
        private Dictionary<string , SensorAlertInfo> dic_AlertInfos = new Dictionary<string , SensorAlertInfo>( );

        /// <summary>
        /// 当前传感器的故障字典
        /// </summary>
        private Dictionary<string , SensorFaultInfo> dic_FaultInfos = new Dictionary<string , SensorFaultInfo>( );

        private Dictionary<string , SensorInfo> dic_SensorInfos = new Dictionary<string , SensorInfo>( );

        /// <summary>
        /// 建立读写锁,保护资源的读取及写入,避免竞争
        /// </summary>
        private ReaderWriterLock rwl = new ReaderWriterLock( );

        /// <summary>
        /// 同步修改对象
        /// </summary>
        private object syncObject = new object( );

        /// <summary>
        /// 综合处理一批异常记录
        /// </summary>
        /// <param name="records"></param>
        public AlertAndFault PerformAlertAndFaultRecords( )
        {
            bool changedAlert = false;
            bool changedFault = false;
            DateTime t = DateTime.Now;
            try
            {
                List<ExcessRecord> records = TakeExcessRecords( );

                List<SensorFaultInfo> list_FaulInfo = new List<SensorFaultInfo>( );
                List<SensorAlertInfo> list_AlertInfo = new List<SensorAlertInfo>( );

                //rwl.AcquireWriterLock(Timeout.Infinite);
                try
                {
                    foreach ( ExcessRecord record in records )
                    {
                        try
                        {
                            changedAlert |= PerformAlertRecord( record , list_AlertInfo );

                            changedFault |= PerformFaultRecord( record , list_FaulInfo );
                        }
                        finally
                        {
                            // 让出CPU
                            // Thread.Sleep(1);
                        }

                        PerformRealRecord( record );
                    }
                }
                finally
                {
                    //rwl.ReleaseWriterLock();
                    if ( changedAlert )
                    {
                        List<SensorAlertInfo> list1;
                        list1 = dic_AlertInfos.Values.ToList( );
                        lock ( syncObject )
                        {
                            list_CurrentAnalogAlertInfo = list_AlertInfo.FindAll( info => info.Modality == Eflong.MonitoringLib.MonitoringUnit.MonitoringUnitModality.Modalities.Analog );
                            list_CurrentDigitalAlertInfo = list_AlertInfo.FindAll( info => info.Modality == Eflong.MonitoringLib.MonitoringUnit.MonitoringUnitModality.Modalities.Digital );
                            List_SensorAlertInfo = list1.ToList( );
                        }
                        list_AlertInfo.Clear( );
                        list_AlertInfo = null;
                        list1.Clear( );
                        list1 = null;
                    }
                    if ( changedFault )
                    {
                        List<SensorFaultInfo> list2;
                        list2 = dic_FaultInfos.Values.ToList( );
                        lock ( syncObject )
                        {
                            list_CurrentFaultInfo = list_FaulInfo.ToList( );
                            List_SensorFaultInfo = list2.ToList( );
                        }
                        list_FaulInfo.Clear( );
                        list_FaulInfo = null;
                        list2.Clear( );
                        list2 = null;
                    }

                    double time = DateTime.Now.Subtract( t ).TotalSeconds;
                    if ( time > 3 )
                    {
                        LogWrapper.Logger.Warn( "DealAlertAndFaultRecords 占用时间太长...........  " + time.ToString( ) );
                    }
                }
            }
            catch ( ApplicationException ex )
            {
                LogWrapper.Logger.Error( "DealAlertAndFaultRecords: " + ex.Message );
                changedAlert = true;
            }
            AlertAndFault result = changedAlert && changedFault ? AlertAndFault.AlertFault : changedAlert ? AlertAndFault.Alert : changedFault ? AlertAndFault.Fault : AlertAndFault.None;
            return result;
        }

        /// <summary>
        /// 处理实时数据
        /// </summary>
        /// <param name="record"></param>
        private void PerformRealRecord( ExcessRecord record )
        {
            // 通信正常
            SensorInfo info;
            string symbol = GetSymbol( record );
            BaseMonitoringUnit unit = CoalMineUnitManager.Instance( ).GetMonitoringUnit( record.CoalMineId , record.MonUnitId );
            if ( unit == null ) return;

            if ( dic_SensorInfos.ContainsKey( symbol ) )
            {
                info = dic_SensorInfos[ symbol ];
                if ( info.Value != record.Value || info.State != record.State )
                {
                    info.tmUpdate = DateTime.Now;
                }
                info.Value = record.Value;
                info.State = record.State;
                if ( record.Modality == Modalities.Digital )
                {
                    info.StateChangeTime = record.Time;
                    info.DataChangeTime = record.Time;
                }
                else
                {
                    info.StateChangeTime = unit.m_timeStateChange;
                    info.DataChangeTime = record.Time;
                }
                info.tmStop = record.Time;
            }
            else
            {
                if ( record.Modality == Modalities.Digital )
                {
                    info = new SensorInfo( )
                    {
                        symbol = symbol ,
                        CoalMineId = record.CoalMineId ,
                        CoalMineName = record.CoalMineName ,
                        MonUnitId = record.MonUnitId ,
                        Name = record.MonUnitName ,
                        Modality = record.Modality ,
                        sType = record.MonUnitType ,
                        ValueDecs = new string[ 3 ] {
                              unit.m_strStateName[0],    unit.m_strStateName[1], unit.m_strStateName[2]
                            } ,
                        tmStart = record.Time ,
                        tmStop = record.Time ,
                        tmUpdate = DateTime.Now ,
                        Value = record.Value ,
                        State = record.State ,
                        StateChangeTime = record.Time ,
                        DataChangeTime = record.Time ,
                        IsRecord = false
                    };
                }
                else
                {
                    info = new SensorInfo( )
                    {
                        symbol = symbol ,
                        CoalMineId = record.CoalMineId ,
                        CoalMineName = record.CoalMineName ,
                        MonUnitId = record.MonUnitId ,
                        Name = record.MonUnitName ,
                        Modality = record.Modality ,
                        sType = record.MonUnitType ,
                        sUnit = record.MonUnitUnit ,
                        DataChangeTime = record.Time ,
                        StateChangeTime = unit.m_timeStateChange ,
                        Value = record.Value ,
                        State = record.State ,
                        tmStart = record.Time ,
                        tmStop = record.Time ,
                        tmUpdate = DateTime.Now ,

                        // 模拟量的特性参数
                        AlertValue = unit.m_fUpperLimit ,
                        UpperLimit = unit.m_fUpperLimit ,
                        IsRecord = false
                    };
                    if ( unit.m_Type == MonitoringUnitType.Types.瓦斯 )
                    {
                        info.BreakValue = unit.m_fBreakLimit;
                        info.RestValue = unit.m_fRestLimit;
                    }
                    else if ( unit.m_Type == MonitoringUnitType.Types.高浓瓦斯 )
                    {
                        info.LowerLimit = unit.m_fLowerLimit;
                        info.UpperLimit = 100;
                    }
                }

                lock ( syncObject )
                {
                    dic_SensorInfos.Add( symbol , info );
                }
            }
        }

        /// <summary>
        /// 处理报警信息
        /// </summary>
        /// <param name="record"></param>
        public bool PerformAlertRecord( ExcessRecord record , List<SensorAlertInfo> list )
        {
            bool changed = false;
            string symbol = GetSymbol( record );
            if ( record.IsFault( ) == false )
            {
                // 通信正常
                SensorAlertInfo alertInfo;

                if ( dic_AlertInfos.ContainsKey( symbol ) )
                {
                    changed = true;
                    alertInfo = dic_AlertInfos[ symbol ];

                    // 判断是否类型改变
                    if ( alertInfo.sType.Equals( record.MonUnitType ) )//&& alertInfo.Name.Equals(record.MonUnitName))
                    {
                        // 类型未改变,名称未改变,认为是一个测点

                        alertInfo.UpdateAlertInfo( record );
                        UpdateOrRemoveAlertInfo( symbol , alertInfo , list );
                    }
                    else
                    {
                        // 类型或名称改变了,认为是原测点结束了

                        alertInfo.tmStop = record.Time;
                        alertInfo.State = record.State;//(Int32)States.UnknownState;

                        alertInfo.IsFinish = true;
                        UpdateOrRemoveAlertInfo( symbol , alertInfo , list );

                        // 再判断是否是新报警

                        if ( record.IsAlert( ) )
                        {
                            changed = true;

                            // 当作新的异常记录
                            SensorAlertInfo alertInfo1;
                            alertInfo1 = AddAlertInfo( record , list , symbol );
                        }
                    }
                }
                else
                {
                    if ( record.IsAlert( ) )
                    {
                        changed = true;

                        // 新的异常记录
                        alertInfo = AddAlertInfo( record , list , symbol );
                    }
                }
            }
            else
            {
                // 通信故障,如果当前正在报警,解除报警
                if ( dic_AlertInfos.ContainsKey( symbol ) )
                {
                    changed = true;
                    SensorAlertInfo alertInfo;
                    alertInfo = dic_AlertInfos[ symbol ];
                    alertInfo.AlertInfoEndByFault( record );
                    UpdateOrRemoveAlertInfo( symbol , alertInfo , list );
                }
            }
            return changed;
        }

        private static string GetSymbol( ExcessRecord record )
        {
            return record.CoalMineId.ToString( ) + "-" + record.MonUnitId;
        }

        private SensorAlertInfo AddAlertInfo( ExcessRecord record , List<SensorAlertInfo> list , string symbol )
        {
            SensorAlertInfo alertInfo;
            alertInfo = new SensorAlertInfo( );
            alertInfo.SetupInfo( record );
            lock ( syncObject )
            {
                if ( dic_AlertInfos.ContainsKey( symbol ) )
                {
                    dic_AlertInfos[ symbol ] = alertInfo;
                }
                else
                {
                    dic_AlertInfos.Add( symbol , alertInfo );
                }
            }
            list.Add( alertInfo.Clone( ) );
            return alertInfo;
        }

        /// <summary>
        /// 解除当前报警
        /// </summary>
        /// <param name="symbol"></param>
        /// <param name="alertInfo"></param>
        private void UpdateOrRemoveAlertInfo( string symbol , SensorAlertInfo alertInfo , List<SensorAlertInfo> list )
        {
            if ( alertInfo.IsFinish )
            {
                // 解除报警了

                if ( alertInfo.Modality != Modalities.Digital )
                {
                    //// 模拟量报警解除

                    lock ( syncObject )
                    {
                        list_AnalogAlertRecordNowForDelete.Add( alertInfo );
                    }
                }
                else
                {
                    // 开关量报警解除
                    lock ( syncObject )
                    {
                        list_digitalAlertRecordNowForDelete.Add( alertInfo );
                    }
                }
                lock ( syncObject )
                {
                    dic_AlertInfos.Remove( symbol );
                }
            }
            else
            {
                list.Add( alertInfo.Clone( ) );
            }
        }

        public void RemoveAlertInfo( string symbol )
        {
            lock ( syncObject )
            {
                if ( dic_AlertInfos.ContainsKey( symbol ) )
                {
                    dic_AlertInfos.Remove( symbol );
                }
            }
        }

        public int GetMaxRecordNum( )
        {
            try
            {
                //rwl.AcquireReaderLock(Timeout.Infinite);
                int max = Math.Max( list_AnalogAlertRecordNowForDelete.Count , list_digitalAlertRecordNowForDelete.Count );

                return Math.Max( list_FaultRecordNowForDelete.Count , max );
            }
            finally
            {
                // rwl.ReleaseReaderLock();
            }
        }

        /// <summary>
        /// 处理故障信息
        /// </summary>
        /// <param name="record"></param>
        public bool PerformFaultRecord( ExcessRecord record , List<SensorFaultInfo> list )
        {
            bool changed = false;
            string symbol = record.CoalMineId.ToString( ) + "-" + record.MonUnitId;
            if ( dic_FaultInfos.ContainsKey( symbol ) )
            {
                SensorFaultInfo faultInfo = dic_FaultInfos[ symbol ];

                // 更新故障信息
                faultInfo.UpdateFaultInfo( record );
                if ( faultInfo.IsFinish )
                {
                    changed = true;

                    // 故障结束
                    // list_FaultInfoHistory.Add(faultInfo);
                    // 已经记录故障信息了,需要删除掉
                    lock ( syncObject )
                    {
                        list_FaultRecordNowForDelete.Add( faultInfo );
                    }
                    lock ( syncObject )
                    {
                        dic_FaultInfos.Remove( symbol );
                    }
                }
            }
            else
            {
                if ( record.IsFault( ) )
                {
                    // 是新的故障

                    changed = true;
                    SensorFaultInfo faultInfo = new SensorFaultInfo( );
                    faultInfo.SetupFaultInfo( record );
                    lock ( syncObject )
                    {
                        dic_FaultInfos.Add( symbol , faultInfo );
                    }
                    list.Add( faultInfo.Clone( ) );
                }
            }
            return changed;
        }

        /// <summary>
        /// 当前报警传感器
        /// </summary>
        public List<SensorAlertInfo> List_SensorAlertInfo { get; set; }

        /// <summary>
        /// 当前故障传感器
        /// </summary>
        public List<SensorFaultInfo> List_SensorFaultInfo { get; set; }

        /// <summary>
        /// 当前全部传感器
        /// </summary>
        public List<SensorInfo> List_SensorInfo { get; set; }

        /// <summary>
        /// 获取全部的报警记录信息
        /// </summary>
        /// <param name="timeOut"></param>
        /// <returns></returns>
        public List<SensorAlert> TakeCurrentAllAlerts( )
        {
            List<SensorAlert> records = new List<SensorAlert>( );
            List<SensorAlertInfo> list_AlertInfo;
            lock ( syncObject )
            {
                list_AlertInfo = List_SensorAlertInfo.ToList( );
            }
            foreach ( SensorAlertInfo info in list_AlertInfo )
            {
                SensorAlert data = new SensorAlert( );
                data.CoalMineId = info.CoalMineId;
                data.CoalMineName = info.CoalMineName;

                data.MonUnitId = info.MonUnitId;
                data.Name = info.Name;
                data.sType = info.sType;

                data.Modality = info.Modality;
                data.Type = info.Type;
                if ( info.Modality == Modalities.Digital )
                {
                    data.ValueDecs = info.ValueDecs;
                }
                else
                {
                    data.Unit = info.sUnit;
                    data.fMaxValue = info.fMaxValue;
                    data.tmMaxValue = info.tmMaxValue;
                    data.fMinValue = info.fMinValue;
                    data.tmMinValue = info.tmMinValue;
                    data.fAvgValue = info.fAvgValue;
                    data.fAlertValue = info.fAlertValue;
                    data.fRelievedValue = info.fRelievedValue;
                }

                data.Value = info.Value;
                data.State = info.State;

                data.tmStart = info.tmStart;
                data.tmStop = info.tmStart; //info.tmStop;

                records.Add( data );
            }

            return records;
        }

        /// <summary>
        /// 清除不报警的报警信息项
        /// </summary>
        /// <param name="info"></param>
        public void RemoveUnAlarmItemFromList_SensorAlertInfo( SensorAlertInfo info )
        {
            lock ( syncObject )
            {
                int index = List_SensorAlertInfo.FindIndex( r => r.CoalMineId == info.CoalMineId && r.MonUnitId == info.MonUnitId );
                if ( index >= 0 && index < List_SensorAlertInfo.Count )
                {
                    List_SensorAlertInfo.RemoveAt( index );
                }
            }
        }

        /// <summary>
        /// 获取当前故障记录
        /// </summary>
        /// <returns></returns>
        public List<SensorFault> TakeCurrentAllFaultRecords( )
        {
            List<SensorFault> records = new List<SensorFault>( );
            List<SensorFaultInfo> list;
            lock ( syncObject )
            {
                list = List_SensorFaultInfo.ToList( );
            }
            foreach ( SensorFaultInfo info in list )
            {
                SensorFault data = new SensorFault( );
                data.CoalMineId = info.CoalMineId;
                data.CoalMineName = info.CoalMineName;

                data.MonUnitId = info.MonUnitId;
                data.Name = info.Name;
                data.sType = info.sType;

                data.State = info.State;

                data.tmStart = info.tmStart;
                records.Add( data );
            }

            return records;
        }

        /// <summary>
        /// 获取当前需要写入报警表的报警记录
        /// </summary>
        /// <param name="nModality"></param>
        /// <returns></returns>
        public List<SensorAlertInfo> TakeCurrentAlertRecords( Modalities nModality )
        {
            List<SensorAlertInfo> records;
            lock ( syncObject )
            {
                if ( nModality == Modalities.Digital )
                {
                    records = list_CurrentDigitalAlertInfo.ToList( );
                    list_CurrentDigitalAlertInfo.Clear( );
                }
                else
                {
                    records = list_CurrentAnalogAlertInfo.ToList( );
                    list_CurrentAnalogAlertInfo.Clear( );
                }
            }
            return records;
        }

        /// <summary>
        /// 获取当前故障记录
        /// </summary>
        /// <returns></returns>
        public List<SensorFaultInfo> TakeCurrentFaultRecords( )
        {
            List<SensorFaultInfo> records;
            lock ( syncObject )
            {
                records = list_CurrentFaultInfo.ToList( );
                list_CurrentFaultInfo.Clear( );
            }
            return records;
        }

        /// <summary>
        /// 设置当前报警写入数据表的记录AutoId
        /// </summary>
        /// <param name="list"></param>
        public void BackCurrentAlertRecords( List<SensorAlertInfo> list )
        {
            lock ( dic_AlertInfos )
            {
                for ( int n = 0; n < list.Count; n++ )
                {
                    SensorAlertInfo info = list[ n ];
                    if ( dic_AlertInfos.ContainsKey( info.symbol ) )
                    {
                        SensorAlertInfo info1 = dic_AlertInfos[ info.symbol ];
                        info1.AutoId = info.AutoId;
                        info1.IsRecord = true;
                        info1.IsNeedRecord = false;
                    }
                }
            }
        }

        /// <summary>
        /// 设置当前故障写入数据表的记录AutoId
        /// </summary>
        /// <param name="list"></param>
        public void BackCurrentFaultRecords( List<SensorFaultInfo> list )
        {
            lock ( dic_FaultInfos )
            {
                for ( int n = 0; n < list.Count; n++ )
                {
                    SensorFaultInfo info = list[ n ];
                    if ( dic_FaultInfos.ContainsKey( info.symbol ) )
                    {
                        SensorFaultInfo info1 = dic_FaultInfos[ info.symbol ];
                        info1.AutoId = info.AutoId;
                        info1.IsRecord = true;
                        info1.IsNeedRecord = false;
                    }
                }
            }
        }

        /// <summary>
        /// 删除当前报警表中已解除报警的记录
        /// </summary>
        /// <param name="nModality"></param>
        /// <returns></returns>
        public SensorAlertInfo[ ] TakeCurrentAlertRecordsForDelete( SensorModalityEnum nModality )
        {
            List<SensorAlertInfo> list = new List<SensorAlertInfo>( );
            SensorAlertInfo[ ] infos = null;
            try
            {
                lock ( syncObject )
                {
                    if ( nModality == SensorModalityEnum.Analog )
                    {
                        infos = list_AnalogAlertRecordNowForDelete.ToArray( );
                        list_AnalogAlertRecordNowForDelete.Clear( );
                    }
                    else
                    {
                        // 获取开关量报警记录
                        // 已经解除了
                        infos = list_digitalAlertRecordNowForDelete.ToArray( );
                        list_digitalAlertRecordNowForDelete.Clear( );
                    }
                }
            }
            catch ( ApplicationException ex )
            {
                LogWrapper.Logger.Error( "TakeCurrentAlertRecordsForDelete: " + ex.Message );
            }
            return infos;
        }

        /// <summary>
        /// 删除当前故障表中已解除故障的记录
        /// </summary>
        public SensorFaultInfo[ ] TakeCurrentFaultRecordsForDelete( )
        {
            SensorFaultInfo[ ] faults = null;
            lock ( syncObject )
            {
                faults = list_FaultRecordNowForDelete.ToArray( );
                list_FaultRecordNowForDelete.Clear( );
            }
            return faults;
        }

        ///
        ///   清除超过 24小时的报警信息
        ///

        ///
        /// 统计最新的时间段的报警信息
        /// 需要避免历史报警表中,和当前报警表中,相同的报警记录
        ///
        /// public SensorAlertInfo[] QueryAlertInfo(int nId1, int nId2 ,DateTime tmStart, DateTime tmStop)
        ///
        /// 查询 矿Id 范围:   nId1 - nId2
        ///
        /// 查询 起止时间 tmStart - tmStop
        ///
        /// 最新的报警统计信息
        /// 按最近 24小时，20小时，16小时，12小时，8小时，4小时，2小时，1小时,分别自动生成
        ///
        ///

        public SensorAlertInfo[ ] QueryAlertInfo( int nId1 , int nId2 , DateTime tmStart , DateTime tmStop )
        {
            List<int> list_NOHis = new List<int>( );
            List<int> list_NONow = new List<int>( );

            rwl.AcquireReaderLock( Timeout.Infinite );
            try
            {
                var hisInfos = from info in list_AlertInfoHistory
                               where
                                   info.CoalMineId >= nId1 && info.CoalMineId <= nId2 && info.tmStop >= tmStart &&
                                    info.tmStop <= tmStop
                               select info;
                var curInfos = from info in dic_AlertInfos.Values
                               where info.CoalMineId >= nId1 && info.CoalMineId <= nId2 && info.IsAlert
                               select info;
                foreach ( SensorAlertInfo info in curInfos )
                {
                    info.tmStop = DateTime.Now;
                    info.fAlertTime = ( ( float )info.tmStop.Subtract( info.tmStart ).TotalSeconds ) / 60;
                }

                var alertInfos = curInfos.Union( hisInfos );

                return alertInfos.ToArray( );
            }
            finally
            {
                rwl.ReleaseReaderLock( );
            }
        }

        ///
        ///
        /// 报警统计
        ///
        ///
        public SensorAlertInfo[ ] AlertStatInfo( int nId1 , int nId2 , DateTime tmStart , DateTime tmStop )
        {
            SensorAlertInfo[ ] alertInfos = QueryAlertInfo( nId1 , nId2 , tmStart , tmStop );

            List<SensorAlertInfo> list_StatInfo = new List<SensorAlertInfo>( );
            bool bFind = false;
            for ( int i = 0; i < alertInfos.Length; i++ )
            {
                SensorAlertInfo info1 = alertInfos[ i ];
                for ( int j = 0; j < list_StatInfo.Count; j++ )
                {
                    SensorAlertInfo info2 = list_StatInfo[ j ];
                    if ( info1.CoalMineId == info2.CoalMineId && info1.MonUnitId == info2.MonUnitId )
                    {
                        // 找到报警了,更新统计
                        info2.StatAlertInfo( info1 );
                        bFind = true;
                        break;
                    }
                }
                if ( !bFind )
                {
                    // 新的报警信息,初始化报警统计

                    SensorAlertInfo info2 = new SensorAlertInfo( );
                    info2.InitAlertInfo( info1 );
                    list_StatInfo.Add( info2 );
                }
            }
            int count = list_StatInfo.Count;
            if ( count > 0 )
            {
                SensorAlertInfo[ ] alertStatInfos = new SensorAlertInfo[ count ];
                for ( int i = 0; i < list_StatInfo.Count; i++ )
                {
                    alertStatInfos[ i ] = list_StatInfo[ i ];
                }
                return alertStatInfos;
            }

            SensorAlertInfo[ ] alertStatInfos1 = new SensorAlertInfo[ 1 ];
            alertStatInfos1[ 0 ] = new SensorAlertInfo( );
            return alertStatInfos1;
        }

        ///
        /// 加入AlertRecord 记录的 AutoId
        ///
        //private void AddAutoId(ExcessRecord ar)
        //{
        //    lock (list_AlertRecord_AutoId)
        //    {
        //        list_AlertRecord_AutoId.Add(ar.AutoId);
        //    }
        //}
        ///
        /// 取出一个 AutoId
        ///
        //public Int32 TakeAutoId()
        //{
        //    lock (list_AlertRecord_AutoId)
        //    {
        //        if (list_AlertRecord_AutoId.Count > 0)
        //        {
        //            Int32 AutoId = list_AlertRecord_AutoId[0];
        //            list_AlertRecord_AutoId.RemoveAt(0);
        //            return AutoId;
        //        }
        //    }
        //    return 0;
        //}

        /*
         *   当前故障表信息
         *
         */
        private List<SensorFaultInfo> list_FaultInfoNow = new List<SensorFaultInfo>( );

        /*
         *   历史故障表信息
         *
         */
        private List<SensorFaultInfo> list_FaultInfoHistory = new List<SensorFaultInfo>( );

        /// <summary>
        /// 建立读写锁,保护资源的读取及写入,避免竞争
        /// </summary>
        private ReaderWriterLock rwlFault = new ReaderWriterLock( );

        /// <summary>
        /// 加入一个故障信息
        /// </summary>
        public void AddFaultInfo( ExcessRecord ar )
        {
            rwlFault.AcquireWriterLock( Timeout.Infinite );
            try
            {
                SensorFaultInfo faultInfo = new SensorFaultInfo( );
                faultInfo.SetupFaultInfo( ar );

                list_FaultInfoNow.Add( faultInfo );
            }
            finally
            {
                rwlFault.ReleaseWriterLock( );
            }
        }

        /// <summary>
        ///  查找故障信息
        /// </summary>
        private int FindAtFaultInfo( ExcessRecord ar )
        {
            rwlFault.AcquireReaderLock( Timeout.Infinite );
            try
            {
                for ( int i = 0; i < list_FaultInfoNow.Count; i++ )
                {
                    SensorFaultInfo faultInfo = list_FaultInfoNow[ i ];
                    if ( faultInfo.CoalMineId == ar.CoalMineId && faultInfo.MonUnitId == ar.MonUnitId )
                    {
                        return i;
                    }
                }
            }
            finally
            {
                rwlFault.ReleaseReaderLock( );
            }
            return -1;
        }

        private void DealFaultInfo( ExcessRecord ar )
        {
            rwlFault.AcquireReaderLock( Timeout.Infinite );
            try
            {
                SensorFaultInfo faultInfo;
                for ( int i = 0; i < list_FaultInfoNow.Count; i++ )
                {
                    faultInfo = list_FaultInfoNow[ i ];
                    if ( faultInfo.CoalMineId == ar.CoalMineId && faultInfo.MonUnitId == ar.MonUnitId )
                    {
                        // return i;
                        if ( faultInfo.IsFault )
                        {
                            faultInfo.UpdateFaultInfo( ar );

                            // 是否解除
                            if ( faultInfo.IsFinish )
                            {
                                // 故障解除,写入历史表

                                SensorFaultInfo info = new SensorFaultInfo( );
                                info = faultInfo;
                                list_FaultInfoHistory.Add( info );

                                // 从当前故障表中,清除故障信息
                                list_FaultInfoNow.RemoveAt( i );
                            }
                        }
                        return;
                    }
                }
                faultInfo = new SensorFaultInfo( );
                faultInfo.SetupFaultInfo( ar );

                list_FaultInfoNow.Add( faultInfo );
            }
            finally
            {
                rwlFault.ReleaseReaderLock( );
            }
            return;
        }

        ///<summary>
        ///  更新一个故障信息
        /// </summary>
        public void UpdateFaultInfo( ExcessRecord ar , int n )
        {
            rwlFault.AcquireWriterLock( Timeout.Infinite );
            try
            {
                SensorFaultInfo faultInfo = list_FaultInfoNow[ n ];
                if ( faultInfo.IsFault )
                {
                    faultInfo.UpdateFaultInfo( ar );

                    // 是否解除
                    if ( faultInfo.IsFinish )
                    {
                        // 故障解除,写入历史表

                        SensorFaultInfo info = new SensorFaultInfo( );
                        info = faultInfo;
                        list_FaultInfoHistory.Add( info );

                        // 从当前故障表中,清除故障信息
                        list_FaultInfoNow.RemoveAt( n );
                    }
                }
            }
            finally
            {
                rwlFault.ReleaseWriterLock( );
            }
        }

        /// <summary>
        /// 查询最近时间的故障信息
        /// public SensorFaultInfo[] QueryFaultInfo(int nId1, int nId2 ,DateTime tmStart, DateTime tmStop)
        ///
        /// 查询 矿Id 范围:   nId1 - nId2
        ///
        /// 查询 起止时间 tmStart - tmStop
        ///
        /// 最新的故障统计信息
        /// 按最近 24小时，20小时，16小时，12小时，8小时，4小时，2小时，1小时,分别自动生成
        /// </summary>

        public SensorFaultInfo[ ] QueryFaultInfo( int nId1 , int nId2 , DateTime tmStart , DateTime tmStop )
        {
            rwl.AcquireReaderLock( Timeout.Infinite );
            try
            {
                var curInfos = from info in list_FaultInfoNow
                               where ( info.CoalMineId >= nId1 && info.CoalMineId <= nId2 )
                               select info;
                List<SensorFaultInfo> tmpInfos = new List<SensorFaultInfo>( );
                foreach ( SensorFaultInfo info in curInfos )
                {
                    SensorFaultInfo info1 = new SensorFaultInfo( );
                    info1 = info;
                    info1.tmStop = DateTime.Now;
                    info1.fFaultTime = ( ( float )info.tmStop.Subtract( info.tmStart ).TotalSeconds ) / 60;
                    tmpInfos.Add( info1 );
                }

                // 采用 LINQ 的查询语句

                var hisInfos = from info in list_FaultInfoHistory
                               where ( info.CoalMineId >= nId1 && info.CoalMineId <= nId2 && info.tmStop >= tmStart &&
                                      info.tmStop <= tmStop )
                               select info;
                var tmpHisInfos = hisInfos.ToList( );

                // 采用联合功能
                var faultInfos = tmpInfos.Union( tmpHisInfos );

                return faultInfos.ToArray( );
            }
            finally
            {
                rwl.ReleaseReaderLock( );
            }
        }

        /// <summary>
        /// 清除资源
        /// </summary>
        public void Cleanup( )
        {
            rwl.AcquireWriterLock( Timeout.Infinite );
            try
            {
                list_AlertInfoHistory.Clear( );
                list_AlertRecord_AutoId.Clear( );
            }
            finally
            {
                rwl.ReleaseWriterLock( );
            }
        }
    }

    // 抽象基类

    public class BaseRecord
    {
        // 自增长Id
        public Int32 AutoId;

        // Id
        public Int32 Id;

        //
        public string Name;

        // 状态改变时刻

        public DateTime StateChangeTime;

        // 数据改变时刻
        public DateTime DataChangeTime;

        // 异常原因
        public string Causation;

        // 采取措施
        public string Measure;

        // 采取措施时刻
        public DateTime MeasureTime;

        // 是否记录
        public bool IsRecord;

        // 需要记录

        public bool IsNeedRecord;

        // 正在报警
        public bool IsAlert;

        // 是否结束
        public bool IsFinished;
    }

    public struct AutoIds
    {
        public Int32 Id1;
        public Int32 Id2;
        public DateTime Time1;
        public DateTime Time2;

        public AutoIds( Int32 id1 , Int32 id2 , DateTime t1 , DateTime t2 )
        {
            Id1 = id1;
            Id2 = id2;
            Time1 = t1;
            Time2 = t2;
        }
    }
}